<?php

namespace App\Kuafu\Pay\Channel\Mybank;

use App\Exceptions\BaseException;
use App\Kuafu\Mybank\Model\MybankEntryModel;
use App\Kuafu\Mybank\Model\MybankOrderRecordModel;
use App\Kuafu\Mybank\Model\MybankOrderWithholdRecordModel;
use App\Kuafu\Mybank\Service\MybankEntryService;
use App\Kuafu\Mybank\Service\MybankOrderWithholdV2Service;
use App\Kuafu\Pay\BasePay;
use App\Kuafu\Pay\Enum\BasePayEnum;
use App\Kuafu\Pay\Enum\FuYouPayEnum;
use App\Kuafu\Pay\Enum\MyBankPayEnum;
use App\Kuafu\Pay\Enum\PayCodeEnum;
use App\Kuafu\Pay\Exceptions\PayException;
use App\Kuafu\Pay\Model\PayStreamModel;
use App\Kuafu\Pay\Model\RefundStreamModel;
use GuzzleHttp\Exception\GuzzleException;

class MybankPay extends BasePay
{
    protected function initConfig(int $shopId, int $sysType)
    {
        // TODO: Implement initConfig() method.
    }

    public function faceToFacePay(string $subject, int $amount, string $authCode)
    {
        // TODO: Implement faceToFacePay() method.
    }

    public function closePay(string $outTradeNo): array
    {
        // TODO: Implement closePay() method.
        return [];
    }

    public function refund(string $outTradeNo, int $refundAmount)
    {
        $model = new MybankOrderWithholdV2Service();

        $subject = PayStreamModel::SYS_TYPE_TEXT[$this->sysType] ?? '退款 - ';
        $subject .= "{$refundAmount}分";

        $result = $model->openStepGenRefundWithholdOrder($outTradeNo, $refundAmount, $subject);

        $formatRes         = $this->commonReturn($result);
        $formatRes['data'] = [
            'thirdRefundNo' => $result['data']['outRefundNo'] ?? '',
            'refundStatus'  => $this->convertRefundStatus($result['data']['status'] ?? 0),
        ];

        return $formatRes;
    }

    public function query(string $outTradeNo)
    {
        $payStream = PayStreamModel::suffix(null)->where('payNo', $outTradeNo)->first();
        if (!$payStream) {
            throw new PayException(PayCodeEnum::ERR_PAY_DATA_NOT_EXIST);
        }

        $result = MybankOrderWithholdV2Service::getWithholdOrderInfo($payStream->thirdPayNo);

        $formatRes = $this->commonReturn($result);

        // 转换支付状态
        $formatRes['data'] = [
            'commonTradeStatus' => $this->convertTradeStatus($result['data']['status'] ?? 0),
            'totalPrice'        => (int)$payStream->payPrice,
            'payNo'             => $outTradeNo,
            'thirdPayNo'        => $payStream->thirdPayNo,
            'paySuccessTime'    => $result['data']['finishDateTime'] ?? 0,
        ];
        return $formatRes;
    }

    public function refundQuery(string $outTradeNo, string $outRequestNo)
    {
        $thirdRefundNo = (string)RefundStreamModel::query()->where('refundNo', $outRequestNo)->value('thirdRefundNo');

        $result = MybankOrderWithholdV2Service::getWithholdRefundOrderInfo($thirdRefundNo);

        $formatRes = $this->commonReturn($result);

        $formatRes['data'] = [
            'payNo'             => $outTradeNo,
            'refundNo'          => $outRequestNo,
            'thirdRefundNo'     => $result['data']['refundOrderNo'] ?? 0,
            'totalAmount'       => $result['data']['refundAmount'] ?? 0,
            'refundStatus'      => $this->convertRefundStatus($result['data']['status'] ?? 0),
            'refundSuccessTime' => $result['data']['refundFinishDate'] ?? 0,
        ];

        return $formatRes;
    }

    public function downloadBill(string $date)
    {
        // TODO: Implement downloadBill() method.
    }

    protected function commonReturn($result): array
    {
        $code = $result['code'] ?? '';
        $msg  = $result['msg'] ?? '';

        if ($code == 200) {
            $status = true;
        } else {
            $status = false;
        }

        return self::returnFormatData($status, $code, $msg, $result);
    }

    /**
     * @throws GuzzleException
     * @throws BaseException
     */
    public function appPay(string $subject, int $amount, int $expireTime = 0): array
    {
        // 用户注册校验
        $register = MybankEntryService::registerStatus($this->userId);
        if ($register['status'] != MybankEntryModel::STATUS_3) {
            return self::returnFormatData(false, '1001', '用户未注册网商', []);
        }

//        $pay = MybankService::getMerchantBalance('', $this->userId);
//        $balance = ($pay['PAY'] ?? 0);
//        if ($balance < $amount) {
//            return self::returnFormatData(false, '1001', '余额不足', []);
//        }

        $model = new MybankOrderWithholdV2Service((string)$this->shopId);

        $tranId = $this->getOutTradeNo();

        $type   = MybankOrderRecordModel::TYPE_KFOS_ORDER;

        // 订货收款账户配置id 存在则查配置里的
        $payeeInfo = [];
        if (isset($this->payConfig['companyAccount']) && $this->payConfig['companyAccount'] && isset($this->payConfig['payeeType']) && $this->payConfig['payeeType']) {
            $payeeInfo = [
                'payeeId'   => $this->payConfig['companyAccount'],
                'payeeType' => $this->payConfig['payeeType'],
            ];
        }
        $result = $model->oneStepGenWithholdOrder($this->userId, $amount, $tranId, $type, $subject, $amount, $payeeInfo);

        $formatRes         = $this->commonReturn($result);
        $formatRes['data'] = [
            'payNo' => $tranId,
            'thirdPayNo' => $result['data']['outTradeNo'] ?? '',
        ];

        return $formatRes;
    }

    /**
     * 获取手续费
     * @param int $payPrice
     * @return float
     */
    public function getFeeAmtByPayPrice(int $payPrice): array
    {
        return [
            round($payPrice * MyBankPayEnum::PAYMENT_RATE), // fee
            number_format(MyBankPayEnum::PAYMENT_RATE, 6, '.', ''), // feeRate
        ];
    }

    /**
     * 转换支付状态
     * @param string $apiTradeStatus
     * @return int
     */
    protected function convertTradeStatus(string $apiTradeStatus): int
    {
        return [
            MybankOrderWithholdRecordModel::WITHHOLD_STATUS_DEFAULT   => BasePayEnum::TRADE_STATUS_WAIT,
            MybankOrderWithholdRecordModel::WITHHOLD_STATUS_SUBMIT   => BasePayEnum::TRADE_STATUS_WAIT,
            MybankOrderWithholdRecordModel::WITHHOLD_STATUS_SUCCESS   => BasePayEnum::TRADE_STATUS_OK,
            MybankOrderWithholdRecordModel::WITHHOLD_STATUS_FAIL   => BasePayEnum::TRADE_STATUS_CLOSED,
        ][$apiTradeStatus] ?? BasePayEnum::TRADE_STATUS_WAIT;
    }

    /**
     * 转换退款状态
     * @param string $apiRefundStatus
     * @return int
     */
    protected function convertRefundStatus(string $apiRefundStatus): int
    {
        return [
            MybankOrderWithholdRecordModel::WITHHOLD_STATUS_DEFAULT => BasePayEnum::REFUND_STATUS_NULL,
            MybankOrderWithholdRecordModel::WITHHOLD_STATUS_SUBMIT  => BasePayEnum::REFUND_STATUS_WAIT,
            MybankOrderWithholdRecordModel::WITHHOLD_STATUS_SUCCESS => BasePayEnum::REFUND_STATUS_OK,
            MybankOrderWithholdRecordModel::WITHHOLD_STATUS_FAIL    => BasePayEnum::REFUND_STATUS_ERROR,
        ][$apiRefundStatus] ?? BasePayEnum::REFUND_STATUS_WAIT;
    }
}
